package com.orchard.orchardfarmmanagementsystem.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orchard.orchardfarmmanagementsystem.dto.ResetPasswordDTO;
import com.orchard.orchardfarmmanagementsystem.dto.TaskEvaluationDTO;
import com.orchard.orchardfarmmanagementsystem.dto.UserRoleDTO;
import com.orchard.orchardfarmmanagementsystem.entity.*;
import com.orchard.orchardfarmmanagementsystem.mapper.*;
import com.orchard.orchardfarmmanagementsystem.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;
    
    @Autowired
    private TaskExecutorRelationMapper taskExecutorRelationMapper;

    @Autowired
    private PermissionMapper permissionMapper;


    @Override
    public User findByUsername(String username) {
        return userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
    }

    @Override
    public boolean authenticate(String username, String password) {
        User user = findByUsername(username);
        return user != null && user.getPassword().equals(password);
    }

    @Override
    public List<User> getAllUsers() {
        List<Map<String, Object>> userMaps = userMapper.selectActiveUsersWithWorkerRole();

        return userMaps.stream().map(userMap -> {
            User userDTO = new User();
            userDTO.setUserId((Integer) userMap.get("user_id"));
            userDTO.setUsername((String) userMap.get("username"));
            userDTO.setAvatarUrl((String) userMap.get("avatar_url"));
            userDTO.setEmail((String) userMap.get("email")); // 如果需要展示
            userDTO.setPhone((String) userMap.get("phone")); // 如果需要展示
            userDTO.setRegistrationDate((LocalDateTime) userMap.get("registration_date"));
            userDTO.setLastLoginDate((LocalDateTime) userMap.get("last_login_date"));
            userDTO.setIsActive((Integer) userMap.get("is_active"));
            userDTO.setCreatedAt((LocalDateTime) userMap.get("created_at"));
            userDTO.setUpdatedAt((LocalDateTime) userMap.get("updated_at"));
            userDTO.setPassword(""); // 清空密码字段

            return userDTO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<UserRoleDTO> getAllUsersAndRole() {

        return userMapper.selectUsersWithRoles();
    }

    @Override
    public List<Role> getAllRoles() {
        List<Role> roles = roleMapper.selectList(null);
        if (roles != null) {
            return roles;
        }
        throw new RuntimeException("获取角色信息失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUser(UserRoleDTO userRoleDTO) {
        // 创建用户
        User user = new User();
        BeanUtils.copyProperties(userRoleDTO, user);
        int insertUserResult = userMapper.insert(user);

        if (insertUserResult <= 0) {
            throw new RuntimeException("新增用户信息失败");
        }

        Integer userId = user.getUserId();

        // 获取角色
        String roleDescription = userRoleDTO.getRole();
        Role role = roleMapper.selectOne(new QueryWrapper<Role>().eq("description", roleDescription));

        if (role == null) {
            throw new RuntimeException("指定的角色不存在");
        }

        // 分配角色给用户
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        userRole.setRoleId(role.getRoleId());
        userRole.setAssignedAt(LocalDateTime.now());

        int insertUserRoleResult = userRoleMapper.insert(userRole);

        if (insertUserRoleResult <= 0) {
            throw new RuntimeException("分配用户角色失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editUser(Integer id, UserRoleDTO userDTO) {
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 更新用户信息
        BeanUtils.copyProperties(userDTO, user);
        int updateUserResult = userMapper.updateById(user);

        if (updateUserResult <= 0) {
            throw new RuntimeException("更新用户信息失败");
        }

        // 获取新的角色描述，并根据该描述查询对应的角色ID
        String roleDescription = userDTO.getRole();
        Role role = roleMapper.selectOne(new QueryWrapper<Role>().eq("description", roleDescription));

        if (role == null) {
            throw new RuntimeException("指定的角色不存在");
        }

        Integer roleId = role.getRoleId();

        // 更新用户与角色的关联
        // 先删除旧的角色关联
        int deleteOldRoleResult = userRoleMapper.delete(new QueryWrapper<UserRole>().eq("user_id", id));

        // 插入新的角色关联
        UserRole newUserRole = new UserRole();
        newUserRole.setUserId(id);
        newUserRole.setRoleId(roleId);
        newUserRole.setAssignedAt(LocalDateTime.now());

        int insertNewRoleResult = userRoleMapper.insert(newUserRole);

        if (deleteOldRoleResult < 0 || insertNewRoleResult <= 0) {
            throw new RuntimeException("更新用户角色关联失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUser(Integer id) {
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        Integer count = taskExecutorRelationMapper.selectCount(new QueryWrapper<TaskExecutorRelation>().eq("user_id", id));
        if(count > 0){
            throw new RuntimeException("用户已关联农事任务无法删除！");
        }

        // 删除用户角色关联
        userRoleMapper.delete(new QueryWrapper<UserRole>().eq("user_id", id));

        // 删除用户
        int deleteUserResult = userMapper.delete(new QueryWrapper<User>().eq("user_id",id));

        if (deleteUserResult <= 0) {
            throw new RuntimeException("删除用户信息失败");
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPassword(Integer id, ResetPasswordDTO resetPasswordDTO) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("user_id", id));
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }

        // 验证旧密码（如果需要）
        if (!user.getPassword().equals(resetPasswordDTO.getOldPassword())) {
            throw new RuntimeException("旧密码不正确");
        }

//        // 检查新密码和确认密码是否一致
//        if (!resetPasswordDTO.getNewPassword().equals(resetPasswordDTO.getConfirmPassword())) {
//            throw new RuntimeException("新密码和确认密码不一致");
//        }

        // 设置新密码
        user.setPassword(resetPasswordDTO.getNewPassword());

        int updateUserResult = userMapper.updateById(user);

        if (updateUserResult <= 0) {
            throw new RuntimeException("重置用户密码失败");
        }

    }

    @Override
    public List<SimpleGrantedAuthority> loadUserAuthorities(Integer userId) {
        // 加载用户的所有角色并添加 'ROLE_' 前缀
        List<Role> roles = roleMapper.selectRolesByUserId(userId);
        Set<String> roleNames = roles.stream()
                .map(role -> "ROLE_" + role.getName())
                .collect(Collectors.toSet());

        // 加载用户的所有权限
        List<Permission> permissions = permissionMapper.selectPermissionsByUserId(userId);
        Set<String> permissionCodes = permissions.stream()
                .map(Permission::getCode)
                .collect(Collectors.toSet());

        // 将角色和权限转换为 GrantedAuthority 列表
        return Stream.concat(
                roleNames.stream().map(SimpleGrantedAuthority::new),
                permissionCodes.stream().map(SimpleGrantedAuthority::new)
        ).collect(Collectors.toList());
    }
}
